<template>
  <Form ref="dom" :model="value">
    <Row :gutter="8">
      <template v-for="config in newConfigs" :key="config.key">
        <Col v-bind="config.wrapperCol" v-if="config.when(value)">
          <Form.Item v-bind="config.formItemAttrs" :label-col="config.labelCol">
            <Switch
              v-if="config.type.name === 'ASwitch'"
              v-bind="config.componentAttrs"
              :checked="Boolean(value[config.key])"
              @update:checked="
                (e) => {
                  handleChange({
                    key: config.key,
                    value: config.componentAttrs?.useNumber ? +e : e,
                  });
                  config.componentAttrs.onChange?.({ update: handleChange, value: value });
                }
              "
            />
            <component
              v-else
              :is="config.type"
              v-bind="config.componentAttrs"
              :config="config"
              :value="value[config.key]"
              @update:value="(e:string|number|any) => {
                if(e?.key) {
                  handleChange({ key: e.key, value: e.value });
                } else {
                  handleChange({ key: config.key, value: e });
                }
                config.componentAttrs.onChange?.({ update:handleChange, value: value })
              }"
            />
          </Form.Item>
        </Col>
      </template>
      <slot />
    </Row>
  </Form>
</template>
<script lang="tsx" setup>
import {
  Col, Form, Row, Switch,
} from 'ant-design-vue';
import {
  computed, onMounted, type PropType, ref,
} from 'vue';

import { type FormItemConfig } from './ConfigFormType';

const props = defineProps({
  configs: {
    type: Array as PropType<FormItemConfig[]>,
    default: () => [],
  },
  form: {
    type: Object,
    default: () => ({}),
  },
  value: {
    type: Object,
    default: () => ({}),
  },
  labelCol: {
    type: Object,
    default: () => ({}),
  },
  readonly: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  wrapperCol: {
    type: Object,
    default: () => ({}),
  },
});
const emit = defineEmits(['change', 'update:value', 'update:form']);
const newConfigs = computed(() => props.configs.map((config) => {
  const {
    wrapperCol, labelCol, when, type, key = '', attrs, children, model, ...rest
  } = config;
  const formItemAttrs = {
    name: key,
    model,
    ...rest,
  } as Record<string, any>;
  const componentAttrs = {
    ...attrs,
    disabled: Boolean(props.disabled || attrs?.disabled),
    readonly: Boolean(props.readonly || attrs?.readonly),
  } as Record<string, any>;

  return {
    key,
    name: [key],
    type,
    children,
    when: when || (() => true),
    labelCol: labelCol || props.labelCol || {},
    wrapperCol: wrapperCol || props.wrapperCol || {},
    componentAttrs,
    formItemAttrs,
    raw: config,
  };
}));

const handleChange = ({ key, value }: any) => {
  const temp = props.value;
  temp[key] = value;
  emit('update:value', temp);
  emit('change', { key, value });
};
const dom = ref();
onMounted(() => {
  emit('update:form', dom.value);
});
</script>

<style></style>
